Skip to content

Mirror uptizm's agent tooling: make the worktree path work, and measure the parts that were only asserted - #12

Merged
anilcancakir merged 10 commits into
mainfrom
feature/agent-tooling-mirror
Sep 5, 2026
Merged

Mirror uptizm's agent tooling: make the worktree path work, and measure the parts that were only asserted#12
anilcancakir merged 10 commits into
mainfrom
feature/agent-tooling-mirror

Conversation

@anilcancakir

Copy link
Copy Markdown
Contributor

The mirror of uptizm#139, per the boilerplate contract: a structural change there (a rule, a skill, the component contract, tooling like bin/check) travels here in the same piece of work. Product code does not.

What travels

  • bin/sync-registry, which generates docs/component-registry.md from the component, layout and preview directories, plus the registry job in bin/check that fails when it is stale. The registry had been hand-maintained and drifted, which is worse than not having one, because the file is trusted.
  • bin/sync-skills, which copies the magic-framework and wind-ui skills into .github/skills/ so a reviewer with only this checkout has them, each carrying the hash CI checks it against.
  • The worktree fix. A fresh worktree is missing the gitignored files it needs, and the copy list was incomplete: it now carries all three, and bin/check refuses a run whose dependency resolution would silently measure pub.dev instead of the local checkouts.
  • A pint failure reported at the moment the file is written, through the PostToolUse hook, rather than at the end of a run.
  • The agent instructions, rewritten around what is actually enforced, with the two new gates recorded and a claim about the worktree copy corrected.

Verification

bin/check green on both halves in this worktree: flutter-analyze, design-tokens, registry, backend-pint, flutter-test, backend-test.

…age skills

Mirrored from uptizm, which found both defects while comparing the two repos.

`docs/component-registry.md` carried `generated: manual (design:registry planned)`
and `last_updated: 2026-06-25`, and what it documented was `magic_starter`'s generic
library rather than this repository's. All three components under
`lib/ui/components/` appeared nowhere in it. That is the worst shape a registry can
take, because AGENTS.md sends a reader there before writing a widget: they conclude
the component does not exist and scaffold a second one.

`bin/sync-registry` writes it from `lib/ui/components/` and `lib/preview/`, and
renders a missing preview or a missing `index.dart` as a bold cell rather than
omitting it, so a rule violation appears in a table a reviewer already reads. It
discovers components rather than listing them, which matters here more than in a
product repo: this is a fork base, and the three components are examples to replace.

`bin/sync-skills` copies the `magic-framework` and `wind-ui` skills from the sibling
working trees into `.github/skills/`, where a reviewer with only this checkout can
read them. Copies rather than symlinks, because the source is a separate repository
and a link resolves to nothing on GitHub. Each copy records the sha256 of its source,
which lets a checkout without the siblings verify it was not hand-edited even though
it cannot check upstream freshness. Only two of the five sibling skills travel:
`artisan`, `dusk` and `telescope` describe tools that drive a running app, which a
reviewer looking at a diff cannot use.
…t would measure pub.dev

AGENTS.md said two mechanisms copy the three gitignored files a worktree needs and
that neither covers every path alone. Only one of them was true: `bin/check` copied
all three, while `.worktreeinclude` carried `pubspec_overrides.yaml` and nothing else.
So a worktree Claude Code created had no `backend/.env` and no `.artisan/plugins.json`,
and each of those fails without naming itself: artisan aborts before it says why, and
every plugin command disappears from `./bin/fsa`.

The root `.env` is deliberately still absent from that list, and the file now says so:
it is committed rather than gitignored, because it is a bundled pubspec asset and a
missing asset fails `flutter build`. The copier only handles gitignored files, and a
tracked one is in the worktree already.

`bin/check` gains `require_local_siblings`, which refuses when `pubspec_overrides.yaml`
is absent or points at a directory that has moved. Without it the siblings resolve from
pub.dev, `flutter pub get` succeeds, and the suite passes against the PUBLISHED packages
while the diff under review is of the local ones. Nothing errors; the run just measures
something else. It also gains a `registry` job so a stale component registry fails
locally rather than only in CI.
`Backend (pint + tests)` is a required check, so a style violation that reaches a push
costs a CI round. A PostToolUse hook runs `vendor/bin/pint --test` on each `.php` file
Claude writes and returns the failure into the session.

It is registered in `.claude/settings.json` rather than `settings.local.json`. The
latter is gitignored, a worktree is a fresh checkout, and work in this repo happens in
worktrees, so the hook would be silent exactly where it is needed. The cost is that it
runs for anyone who clones this template. The script is read-only by construction
(`--test` reports rather than rewrites), the executable name is baked in at authoring
time and never read from repository content, it resolves both sides of the path
comparison before deciding a file is inside the project, and it skips `.git`, any
`.env`, `vendor/`, and anything shaped like a key.

Proven here rather than assumed: a file pint rejects produces the report, a path
outside the project is refused, and `jq -e` confirms the matcher and command nest where
the runtime looks for them. It exits silently when `backend/vendor/` is absent, which
is the state of a fresh clone rather than a fault, and that is why the first attempt at
the proof looked like a broken hook.

`worktree.baseRef` is set to `fresh` in the same file, so a new worktree branches from
the remote default rather than from a local `main` that may be behind.
… worktree copy

AGENTS.md said `.worktreeinclude` and `bin/check` together covered the three gitignored
files a worktree needs. They do now; the sentence was written before that was true and
is corrected in place rather than deleted, because the shape of the mistake is the
useful part: a file listed in one mechanism and not the other reads as covered.

The verification section gains the two gates that live only in CI (the `.github`
mirrors and the package skill copies), the registry job, and the linting hook with the
one state in which it is deliberately silent. The generated-files list gains
`docs/component-registry.md` and `.github/skills/`.

CI checks both new artifacts in the `Instruction mirrors` job, which needs no toolchain
for either: `sync-skills --check` falls back to the recorded hash when the siblings are
absent, and `sync-registry --check` is Python over `lib/`.
@kodizm

kodizm Bot commented Sep 5, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

The two new --check gates are sound and pass on this checkout, but the pubspec_overrides.yaml guard is a silent no-op wherever PyYAML is not installed - which is exactly the class of failure the rest of this PR exists to close.

Major

bin/check:139 (correctness) - the stale-path half of require_local_siblings never runs unless PyYAML happens to be installed. import yaml sits outside the try, so an ImportError writes a traceback to stderr, leaves stdout empty, and missing comes back empty. bin/check runs with set -u -o pipefail and no -e, so the failing command substitution does not stop the run either: a pubspec_overrides.yaml whose absolute paths point at a moved sibling passes the guard, and you get pub's opaque resolution error with no hint of the file, which is the outcome the comment above the function says it prevents. Evidence, on this checkout:

$ python3 -c "import yaml"
ModuleNotFoundError: No module named 'yaml'
$ # same heredoc as bin/check, against dependency_overrides: {magic: {path: /nonexistent/magic}}
STALE PATH -> missing=[] verdict=guard PASSES (no-op)

Nothing in the repo declares PyYAML: bin/design-tokens is bash/awk, bin/sync-instructions is bash, and bin/sync-registry is stdlib-only Python. Either move import yaml inside the try and fail loudly on ImportError, or parse the two lines needed with re and drop the dependency.

bin/check:137 - bin/check and bin/check flutter now refuse to run at all in any checkout without pubspec_overrides.yaml, with no opt-out flag. That includes a fresh clone of this repo and every fork - and AGENTS.md opens with "Production apps in this ecosystem fork this project". In a fork there are no sibling working trees, so hosted resolution is the correct answer, and ci.yml:8 says as much for CI. Verified:

$ bin/check flutter --fast
check: pubspec_overrides.yaml is absent, so every sibling would resolve from pub.dev
check: and this run would certify the published packages, not your working trees.

An env escape (CHECK_ALLOW_HOSTED=1) or a downgrade to a warning when no sibling tree exists beside the repo would keep the guard useful without breaking the documented primary audience.

bin/sync-registry:34 - first_prose_line returns only the first /// line of a wrapped doc paragraph, so every "What it is" cell in the generated registry ends mid-sentence. All three rows in the committed output are truncated: "Demonstrates a", "built", "demonstrating a two-axis". For a file whose stated purpose is that an agent reads it before writing a widget, the one descriptive column is unreadable. Joining the doc lines up to the first blank /// or a full stop would fix it.

Minor

bin/sync-registry:76 - a doc line containing a | is emitted straight into the markdown table and splits the row into extra cells. Escaping it in the f-string is a one-liner, and this is a fork base whose components get replaced.

bin/check:145 - the unparseable: <exc> line the Python block prints on a YAML error lands in $missing, which is then reported under the heading "pubspec_overrides.yaml points at paths that do not exist". A malformed file gets told the wrong thing.

Tests

Nothing tests the three new scripts; they are self-verifying through --check, which is a reasonable trade for tooling. Worth noting that the PyYAML gap above survived a green bin/check run precisely because nothing exercises the guard's failing branch.

Checks I ran

  • bin/sync-skills --check - exit 0, both copies match their recorded sha256 (source absent, so the CI branch is what ran; this is the branch CI will take).
  • bin/sync-registry --check - exit 0, committed registry is current.
  • bin/sync-skills (regenerate mode) - exit 1 with a clear "is the magic working tree beside this repo?" message; correct, no siblings here.
  • bin/check backend --fast - stopped at backend/vendor is absent, as designed.
  • bin/check flutter --fast - exit 1 on the new guard (evidence above).
  • Reproduced the PyYAML ImportError path and the stale-path no-op with the exact heredoc from bin/check.
  • git check-ignore -v backend/.env .artisan/plugins.json - both ignored (backend/.gitignore:3, .gitignore:46), so the two new .worktreeinclude entries will actually be copied. bash -c 'set -e; [ a = b ] && X=1' does not exit, so sync-skills' arg parsing is safe.
  • Not run: flutter analyze / flutter test / the PHP suite - no sibling checkouts and no backend/vendor here, and flutter pub get would resolve from pub.dev.
  • Not read line by line: the two generated SKILL.md copies (398 + 491 lines); I verified them by hash instead. .github/copilot-instructions.md I checked only for consistency with the AGENTS.md edits, which it matches.

…entences the registry cuts

Review findings on this PR, fixed here and in uptizm, where the tooling is
authored.

The stale-path guard depended on PyYAML and nothing in this repo declares it.
`import yaml` sat outside the try, so on a machine without it the ImportError
left stdout empty, `missing` came back empty, and the guard PASSED. bin/check
carries `set -u -o pipefail` and no `-e`, so the failed command substitution did
not stop the run either. The file's shape is fixed and machine-written, so it is
parsed with two regexes from the standard library now and the dependency is
gone; a parser that falls over is a hard failure rather than a silent pass.

bin/check also refused to run at all without pubspec_overrides.yaml, with no way
out, and this repo exists to be forked. In a fork there are no sibling working
trees and hosted resolution is the correct answer, so CHECK_ALLOW_HOSTED=1 is
the opt-in escape and the absent-file message names it. Verified against a real
fork rather than a worktree, because bootstrap_ignored_files copies the file
into a worktree before the guard ever sees it missing.

first_prose_line took only the first line of a doc block, and a doc block wraps
at the line length, so all three rows in the registry ended mid-word:
"Demonstrates a", "built", "demonstrating a two-axis". It joins the opening
paragraph now and cuts at the first sentence, so a physical line carrying two
sentences does not drag the whole paragraph into a table cell either.

Also from the review: a `|` in a doc line split its row into extra cells and is
escaped now, and an empty description rendered as a blank cell rather than a gap
and now says so, the same way a missing preview already did.
@anilcancakir

Copy link
Copy Markdown
Contributor Author

All five findings verified against the source and fixed, here and in uptizm#142. The tooling is authored in uptizm and was already on its master, so the same defects were live there too; that PR carries the identical changes.

The PyYAML no-op. Confirmed exactly as described: import yaml outside the try, set -u -o pipefail with no -e, so the failed substitution left missing empty and the guard passed. The file's shape is fixed and machine-written, so it is parsed with two regexes from the standard library now and the dependency is gone. A parser that falls over is a hard failure rather than a silent pass, and a single-line entry such as file_picker: ^11.0.2 clears the pending name so a later path: cannot be attributed to the wrong package.

No opt-out on a fork base. CHECK_ALLOW_HOSTED=1 is the escape and the absent-file message names it. Worth recording how this was verified, because the obvious test does not reproduce: in a worktree, bootstrap_ignored_files copies pubspec_overrides.yaml in from the main checkout before the guard ever sees it missing. Checked against a real git clone instead, which is the fork case:

$ bin/check --fast
check: pubspec_overrides.yaml is absent, so every sibling would resolve from pub.dev
check: and this run would certify the published packages, not your working trees.
check: on a fork with no sibling checkouts, hosted IS correct: CHECK_ALLOW_HOSTED=1 bin/check

$ CHECK_ALLOW_HOSTED=1 bin/check --fast
check: CHECK_ALLOW_HOSTED=1, resolving every sibling from pub.dev
check: backend/vendor is absent here. Run: (cd backend && composer install)

The second run stops at the next legitimate gate, which is the intended behaviour.

The truncated descriptions. Fixed, and the first attempt overshot in a way worth naming: joining the wrapped paragraph and stopping when a physical LINE ends with a terminator pulled whole four-sentence paragraphs into the cells, because one line can carry two sentences. It cuts at the first sentence now. All three rows read as sentences:

  • callout/ - "An inline note with a title and message, tinted by intent."
  • stat_card/ - "A generic dashboard stat: a label, a value, and an optional delta line, built from semantic alias tokens."
  • tag/ - "A compact pill for category or status labels, demonstrating a two-axis [WindRecipe] (intent x size)."

The two minors. A | in a doc line is escaped now. An empty description says **NO DOC** rather than rendering blank, matching how a missing preview already said **NONE**.

On the unparseable: heading: that branch no longer exists. The hand parser has nothing to be unparseable about, and an unreadable file exits non-zero into its own message rather than being reported as a stale path.

On tests: still none for the three scripts, and your point stands that the PyYAML gap survived a green run precisely because nothing exercises the failing branch. I exercised all four paths by hand (healthy, two stale paths, absent file, escape) and recorded the output above; a real test for them is worth its own change rather than being folded in here.

bin/check green on both halves.

@kodizm

kodizm Bot commented Sep 5, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Incremental re-review of 45c189d only: all five earlier findings are genuinely fixed and I verified each one, but the hand-rolled replacement for PyYAML only understands block style, so a flow-style override (magic: {path: ..} - the shape AGENTS.md itself writes) is skipped and a stale path passes again.

Major

bin/check:184 (correctness) - name_re requires the whole line to be <name>:, so an inline-map entry never sets current and its path: is never examined. The old PyYAML parser handled both shapes, so this is a narrowing of coverage, not just a gap. AGENTS.md:10 and :12 both write the override as magic: {path: ..}, and the file is hand-written by a developer in the fluttersdk workspace (nothing in bin/ generates it), so the comment's premise that "the shape here is fixed and machine-written" is the part that does not hold. Evidence, running the exact heredoc from bin/check against two files that differ only in style:

--- block:  magic:\n    path: /nonexistent/magic
magic -> /nonexistent/magic          # guard fails, correct
--- flow:   magic: {path: /nonexistent/magic}
(no output, exit 0)                  # guard PASSES, stale path unreported

One extra regex for ^ ([A-Za-z_]\w*):\s*\{.*path:\s*([^,}]+) closes it, or treat any dependency_overrides line the two regexes cannot classify as a hard failure rather than skipping it - the comment says "anything the parser cannot read is a hard failure now", which is true for I/O errors but not for lines it silently ignores.

Minor

bin/check:155 (maintainability) - CHECK_ALLOW_HOSTED=1 is the right escape and the message names it, but it exists nowhere else. README.md:44 tells a fork to delete pubspec_overrides.yaml as step 5 of forking, and AGENTS.md:26 still states flatly that bin/check refuses without it. A forker following the README hits a hard failure that neither document predicts; one clause in each would fix it.

Tests

Unchanged and still none, which you already answered: the four paths were exercised by hand and recorded. The flow-style case above is the one that hand-exercising missed, which is the argument for the follow-up change you named.

Checks I ran

  • Extracted the bin/check heredoc verbatim and ran it against six override files: block-stale (reported), two-stale-quoted (both reported), healthy (silent), file_picker: ^11.0.2 then stale (attributed correctly, so that fix works), a second top-level block after dependency_overrides (correctly ignored), flow-stale (missed - evidence above).
  • bin/sync-registry --check - exit 0, committed registry current.
  • Probed the new helpers directly: first_sentence cuts correctly on the three committed rows, keeps 0.0.9 and Wait... intact; cell() escapes Time \| Region \| Status and returns **NO DOC** on an empty block. All three registry rows now read as sentences.
  • End-to-end bin/check flutter --fast against a planted flow-style file: not run, the command was declined; the parser-level result above is the same code path.
  • Not run: flutter analyze / flutter test / the PHP suite - no sibling checkouts and no backend/vendor here.
  • Not re-read: everything outside these three files, unchanged since the previous review.

…he escape

Second review pass, and it caught the previous fix reintroducing the failure it
replaced. The hand-rolled parser only understood block style, so
`magic: {path: /gone}` set no current package, its path was never examined, and
a stale flow-style override passed exactly the way the PyYAML gap did. That is a
narrowing against the PyYAML version, which read both.

The premise in the comment was the wrong part: it claimed the file's shape is
"fixed and machine-written". Nothing generates it. It is written by hand, and
AGENTS.md writes the override in the flow form, so the style the parser did not
read is the style this repo's own documentation teaches.

Both forms are covered now, and a `dependency_overrides` line the parser cannot
classify exits non-zero instead of being skipped, which is what makes the claim
about hard failures actually true. A `git:` override has no path to check, so
its nested keys are still ignored rather than treated as unknown.

Exercised against nine shapes: block-stale, flow-stale, flow with a second key,
flow-healthy, quoted flow, a single-line version followed by a stale entry, a
git override, a second top-level block, and an unsupported list form. Only the
last exits non-zero, and the healthy ones stay silent.

The escape existed only in bin/check's own message. README.md step 5 tells a
fork to delete pubspec_overrides.yaml and AGENTS.md said flatly that bin/check
refuses without it, so a forker following the README hit a wall neither document
predicted. Both name CHECK_ALLOW_HOSTED=1 now.
@anilcancakir

Copy link
Copy Markdown
Contributor Author

Both fixed, and the major one was a fair hit: the replacement reintroduced the failure it replaced, in a different shape.

Flow style. Reproduced before fixing, running the heredoc against two files differing only in style, exactly as you did:

--- block:  magic:\n    path: /nonexistent/magic
magic -> /nonexistent/magic     # reported
--- flow:   magic: {path: /nonexistent/magic}
(no output)                     # missed

The premise in my comment was the wrong part, and that is the useful correction: I wrote that the file's shape is "fixed and machine-written". Nothing generates it, AGENTS.md:10 and :12 write it in the flow form, so the style the parser did not read is the style this repo's own documentation teaches. I asserted a property of the input instead of checking it.

Both forms are read now. I took your second suggestion as well as the first, because the comment claimed something that was not true: a dependency_overrides line the parser cannot classify exits non-zero rather than being skipped. A git: override is a legitimate entry with no path to check, so its nested keys are still ignored rather than treated as unknown, which is the one case that rule must not fail on.

Exercised against nine shapes:

shape result
block, stale reported
flow, stale reported
flow with a second key ({path: /nope, hosted: x}) reported
flow, healthy silent
quoted flow ({path: "/nope"}) reported
file_picker: ^11.0.2 then a stale block entry attributed to the right package
git: override silent, no path to check
a second top-level block after dependency_overrides ignored
unsupported list form (- magic) exit 3, hard failure

Then end to end through bin/check --fast, which you noted you could not run: a planted flow-style stale file now fails the gate with check: magic -> /nonexistent/magic, and the list form fails with check: could not read pubspec_overrides.yaml (exit 3).

The docs. Correct, and worse than one clause: README.md step 5 tells a fork to delete the file, so a forker following the README walked straight into a wall the README had just built. Step 5 now names CHECK_ALLOW_HOSTED=1 as the way to run the gate afterwards, and AGENTS.md:26 says which side of the line each case is on: hosted is right for a fork, and reaching for the escape inside this workspace means you are about to certify the wrong packages.

On tests: you are right that hand-exercising is what missed the flow case, and it would have missed it again. Nine shapes by hand is better than four, and it is still the same instrument. A real test for these three scripts is the follow-up, not something to fold in here.

bin/check green on both halves.

…STED note

The instruction-mirror gate is a CI check rather than a bin/check job, so editing
AGENTS.md without running bin/sync-instructions goes green locally and red on the
PR. That is exactly what happened here.
@kodizm

kodizm Bot commented Sep 5, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Incremental re-review of 95a810d + 41d5b50: flow style is genuinely covered now and the fork docs line up on all three files, but the parser is still keyed to two-space indentation, so a four-space or tab-indented override is skipped without ever reaching the hard-failure branch.

Since the last round: bin/check's override parser gained flow-form and unknown-line handling, README.md step 5 and AGENTS.md:26 name CHECK_ALLOW_HOSTED=1, and .github/copilot-instructions.md is the regenerated mirror (bin/sync-instructions --check → "mirrors are up to date").

Major

bin/check:195 (correctness) - the nested branch is line.startswith(' ') and path_re is anchored at exactly four spaces, so an override written with four-space indentation has its <name>: line consumed as "nested" (never setting current) and its eight-space path: line consumed as "nested" (never matching path_re). Nothing is reported and nothing exits non-zero, which is the same silent pass in a third shape - and it does not hit the new exit 3, because both lines are swallowed before the unrecognised-line check. Both indentations are valid YAML for a file the comment above now correctly calls hand-written. Evidence, the heredoc extracted verbatim:

=== block stale (2sp)      exit=0 out=magic -> /nonexistent/magic
=== flow stale             exit=0 out=magic -> /nonexistent/magic
=== 4-space indent stale   exit=0 out=            <- silent pass
=== tab indent stale       exit=0 out=            <- silent pass

and end to end with a four-space file planted:

$ bin/check flutter --fast
check: resolving dart dependencies
Because magic_example depends on magic from path which doesn't exist ... version solving failed.

Requiring the entry key at any consistent indent, or treating a path: line whose owner was never identified as unrecognised, would close it.

Minor

bin/check:181 - a quoted entry key ( "magic":) is legal YAML and matches none of the three regexes, so it now exits 3 and bin/check refuses the whole run on a file that is fine. Loud rather than silent, so it is the right side of the trade, but it is a new way to be blocked by a valid file. Verified: exit=3 unrecognised dependency_overrides line 2: "magic":.

bin/check:189 - flow_re strips a trailing comment, path_re does not, so the block form path: /tmp # local checkout is reported as a path that does not exist while magic: {path: /tmp} # local passes. The block behaviour is unchanged from before this diff; the inconsistency between the two forms is new.

Tests

Still none for these scripts, which you already answered and named as the follow-up. Worth noting the indentation case is the second one hand-exercising missed, both times in the "shapes I did not think of" category that a table-driven test would cover cheaply.

Checks I ran

  • Extracted the bin/check heredoc verbatim and ran it against 15 shapes: block-stale, flow-stale, flow with a second key, quoted flow, flow-healthy, scalar-then-stale (attributed correctly), git: override with and without a nested path: (both correctly silent), multi-line flow (exit 3), list form (exit 3), quoted key (exit 3), four-space and tab indent (silent - above), block/flow trailing comment.
  • bin/check flutter --fast with a four-space stale override planted: passed the guard, failed at flutter pub get (output above). Working tree restored, git status clean.
  • bin/sync-instructions --check - exit 0, mirrors current, so the .github/copilot-instructions.md commit is a faithful regeneration.
  • Read README.md step 5 and AGENTS.md:26 against bin/check:146-155 and :239: the four mentions of CHECK_ALLOW_HOSTED agree.
  • Not run: flutter analyze / flutter test / the PHP suite - no sibling checkouts and no backend/vendor here.
  • Not re-reviewed: everything outside these four files, unchanged since 45c189d.

… shape

Third review round, and the third shape this guard did not read: four-space and
tab indentation. The nested branch tested for exactly four spaces, so a
four-space entry had its name line consumed as "nested" (setting no current
package) and its eight-space path line consumed the same way. Silent pass again,
without even reaching the exit-3 branch added last round, because both lines
were swallowed before the unknown-line check.

The pattern is the finding. PyYAML absent, then flow form, then indentation:
every fix was keyed to the shapes somebody had thought of, so every fix found
the next one.

It walks by INDENT LEVEL now, tracking the open key stack rather than matching
fixed-width line shapes. It expands tabs, accepts a quoted key, and strips a
trailing comment the same way in both forms, which also closes the two smaller
findings: `"magic":` used to exit 3 on a valid file, and `path: /tmp # local`
was reported as missing while the flow form with the same comment passed.

Exercised against fifteen shapes and then end to end through the gate; only an
unsupported list form exits non-zero, and a `git:` override stays silent because
its path is a sub-directory one level deeper.
@anilcancakir

Copy link
Copy Markdown
Contributor Author

All three fixed, and the indentation one is the third round of the same mistake, so I stopped patching shapes.

The pattern is the finding. PyYAML absent, then flow form, then indentation: each fix was keyed to the shapes somebody had thought of, so each one found the next. A fourth patch would have been the same mistake a fourth time. You are right that the exit-3 branch did not help here either, because both lines were swallowed as "nested" before the unknown-line check ever ran.

So it walks the file by indent level now, tracking the open key stack instead of matching fixed-width line shapes. It expands tabs, accepts a quoted key, and strips a trailing comment identically in both forms. What it looks for is one thing: a path: belonging to an entry directly under dependency_overrides, at whatever indent the file uses.

That closes both minors as a side effect rather than as separate patches. "magic": no longer exits 3 on a valid file, and path: /tmp # local checkout no longer reports a path that exists.

Fifteen shapes, parser level and then end to end through bin/check --fast:

shape result
block, 2-space / 4-space / tab reported in all three
flow, one key / two keys / quoted path reported
flow, healthy silent
quoted key "magic": reported, no longer exit 3
trailing comment, block form / flow form both silent, consistent
file_picker: ^11.0.2 then a stale entry attributed to the right package
git: override, with and without a nested path: silent in both
second top-level block ignored
list form - magic exit 3

The git: case is the one worth naming: its path: is a sub-directory inside the repo rather than a checkout, and it sits one level deeper, so the depth rule keeps it silent instead of reporting it as missing. A rule that failed on anything unclassifiable would have got that wrong.

On tests: you have now named the same gap three times and been right three times, so this stops being something I answer and becomes the next change. Hand-exercising fifteen shapes is still hand-exercising, and the shapes I do not think of are precisely the failure mode. A table-driven test over these fifteen is cheap and I will raise it separately rather than growing this PR further.

bin/check green on both halves. The same commit is on uptizm#142.

@kodizm

kodizm Bot commented Sep 5, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Incremental re-review of 4df2516 (only bin/check changed): the indent-walking rewrite genuinely closes all three prior findings and every shape in your table reproduces as you describe, but it opens the mirror of one of them - the git: override the depth rule protects in block form is a false positive in flow form, and fails the gate on a valid file.

Major

bin/check:249 (correctness) - flow_path_re is (?:^|[{,])\s*path\s*:\s*([^,}]+), so it matches the path: nested inside a flow-style git: map. The block form of that same override is correctly silent, because the depth rule sees it one level deeper; the flow form has no depth to see, so the entry is reported and bin/check exits 1 on a file that is fine. Since AGENTS.md:10/:12 teach the flow form, this is the shape a developer here is most likely to write. Evidence, the heredoc extracted verbatim from this commit:

flow git override    exit=0 out=[magic -> packages/magic]     <- false positive
flow git ref         exit=0 out=[]
block git override   exit=0 out=[]                            <- correctly silent

and downstream, :275-278 turns any non-empty missing into exit 1. Anchoring the flow search at the top level of the entry map (rather than search over the whole value) or skipping an entry whose flow map declares git would close it.

Minor

bin/check:243 - dependency_overrides written entirely in flow form on one line (dependency_overrides: {magic: {path: /nope}}) is a silent pass: path_of is [] on that line, neither branch applies, and if not value is false so nothing is pushed. Verified: exit=0, no output, on a stale path. Unlikely shape and much less pressing than the above, but it is the same silent-pass class rather than the intended hard failure.

Tests

Unchanged and still none, which you have now committed to as a separate change - fair. Worth noting the flow-git: case above is exactly the kind a table-driven test over your fifteen shapes would have caught, since it is the block/flow asymmetry you had just fixed for trailing comments, reappearing on a different key.

Checks I ran

  • Extracted the bin/check heredoc verbatim and ran it against 28 shapes. All fifteen in your table reproduce as claimed: block at 2-space/4-space/tab (all reported), flow with one key / two keys / quoted path / quoted key (reported), flow healthy (silent), "magic": (reported, no longer exit 3), trailing comment in block and flow form (both silent, consistent), scalar-then-stale (attributed correctly), git: block form with and without a nested path: (silent), second top-level block (ignored), list form (exit 3).
  • Additional shapes: quoted "path": key, quoted path value, package name with digits, hosted + path flow, sdk: flutter override, comment line inside the block, whitespace-only line, path with spaces - all correct. Multi-line flow map and a list-valued path: both exit 3, so they are loud rather than silent. The two above are the only silent/incorrect results I found.
  • End-to-end bin/check flutter --fast with a flow-git: file planted: not run, the command was declined; :275-278 is the same code path and turns the reported line into exit 1.
  • Not run: flutter analyze / flutter test / the PHP suite - no sibling checkouts and no backend/vendor here.
  • Not re-reviewed: everything outside bin/check, unchanged since 41d5b50.

…ow-form git false positive

Fourth review round found the mirror of the bug the third one fixed. The depth
rule keeps a block-form `git:` override silent, because its `path:` is a
sub-directory one level deeper. The flow form has no depth to see, so the regex
searched the whole value, found the `path:` inside `{git: {..., path: sub}}` and
reported a valid file as stale, failing the gate. That is the block/flow
asymmetry the previous round had just fixed for trailing comments, reappearing
on another key. AGENTS.md teaches the flow form, so it is the shape a developer
here is most likely to write.

Patching stopped. The parser moved out of the heredoc into bin/parse-overrides.py
so it can be tested, and bin/parse-overrides-test.py is a table of 25 shapes run
as a bin/check job. Four rounds found four shapes, each fix keyed to the shapes
somebody had thought of and each one finding the next, because hand-exercising
was the only instrument. A fifth shape costs one row now.

The table earns its place: reinstating the naive flow search turns it red on
"git override, flow form" with exactly the reported false positive. Both go
green again on the fix.

Two behaviour changes beyond that. A flow mapping is split on its TOP-LEVEL
commas, so a nested map's keys are never read as the entry's own. And
`dependency_overrides: {magic: {path: /nope}}`, the whole block inline, used to
pass silently; it is parsed rather than made a hard failure, because it is valid
YAML and refusing a valid file is the mistake the quoted-key case already taught.
@anilcancakir

Copy link
Copy Markdown
Contributor Author

Both fixed, and you found the mirror of the bug the previous round fixed: the block/flow asymmetry I had just closed for trailing comments, reappearing on git:. The depth rule protects the block form and the flow form has no depth to see, so the regex searched the whole value and reported a valid file as stale.

I stopped patching shapes. You have named the test gap four times and been right four times, and every fix I wrote was keyed to the shapes somebody had thought of, which is exactly why each one found the next. So the parser moved out of the heredoc into bin/parse-overrides.py where it can be tested, bin/parse-overrides-test.py is a table of 25 shapes, and it runs as a bin/check job (overrides-parser). A fifth shape costs one row now instead of another round.

The table earns its place rather than decorating the PR. Reinstating the naive flow search turns it red on exactly what you reported:

FAIL git override, flow form: expected [], got ['magic -> packages/magic']
FAIL multi-line flow map: expected an unreadable-shape failure, got none
parse-overrides: 23/25 shapes pass

and green again on the fix, 25/25.

The two fixes. A flow mapping is split on its TOP-LEVEL commas now, so a nested map's keys can never be read as the entry's own; {path: /real, git: {path: sub}} reports /real and ignores sub, which is in the table. And the whole-block-inline form is parsed rather than made a hard failure, because dependency_overrides: {magic: {path: /nope}} is valid YAML and refusing a valid file is the mistake the quoted-key case already taught me.

The git: case is now covered in three shapes: block form, flow form, and flow form with a real path: beside the git map. That last one is the one I would otherwise have got wrong again.

bin/check green on both halves, with the new job in it. Same commit on uptizm#142.

@kodizm

kodizm Bot commented Sep 5, 2026

Copy link
Copy Markdown

Note

Kodizm (AI-generated). May contain mistakes; verify before acting.

Incremental re-review of a742484 (bin/check plus the two new bin/parse-overrides*.py): extracting the parser and giving it a table is the right move, both prior findings are closed, and the 25 shapes pass here - only two minors left, neither about the parser's core logic.

Since the last round: the heredoc moved to bin/parse-overrides.py, bin/parse-overrides-test.py is its table, and overrides-parser is a bin/check job. Flow mappings are now split on top-level commas and the whole-block-inline form is parsed rather than refused.

Minor

bin/parse-overrides.py:151-161 (correctness) - a package entry whose value is a non-empty scalar is never pushed onto the stack, so an entry carrying a YAML anchor or tag before its block child swallows the following path: silently rather than hitting the exit 3 branch. Verified against this commit:

dependency_overrides:
  magic: &m
    path: /nonexistent/anchor
$ python3 bin/parse-overrides.py pubspec_overrides.yaml
(no output)   exit=0

An unlikely shape in a hand-written overrides file, and much narrower than the four it replaces, but it is the same silent-pass class the module docstring says it guards - one more row in the table, or pushing the entry when the scalar is an anchor/tag, would cover it.

AGENTS.md:34 (maintainability) - the enumeration of what bin/check runs still reads "flutter analyze, the design-token scan, the component-registry check, flutter test, pint --test, and the PHP suite" and does not name the new overrides-parser job. bin/sync-instructions --check is green because AGENTS.md itself did not change, so the .github/ mirror carries the same omission at :36.

Tests

bin/parse-overrides-test.py is the gap you named four rounds running, now closed for the parser. It covers scan() only; main()'s exit codes (2 on an unopenable file, 3 on an unreadable shape) and the bin/check wiring around them are still hand-verified rather than tabled - worth one row each if the table grows, since exit 3 is what turns a silent pass into a loud one.

Checks I ran

  • python3 bin/parse-overrides-test.py - parse-overrides: 25/25 shapes pass, exit 0.
  • CHECK_ALLOW_HOSTED=1 bin/check flutter --fast - all green, and overrides-parser appears in the job list alongside flutter-analyze, design-tokens and registry.
  • Both previously reported cases re-run against this commit: flow-form git: override → no output, exit 0 (false positive gone); dependency_overrides: {magic: {path: /nonexistent/inline}}magic -> /nonexistent/inline, exit 0 (silent pass gone).
  • 15 further shapes through scan(): document start ---, CRLF, quoted top-level key, trailing whitespace, relative path, flow list value, quoted "path" key inside a flow map, git: map with no sibling path, inline block mixing a git: entry and a stale one, blank line between entry and child, odd child indents - all correct. The anchor case above is the only silent/incorrect result I found; a hyphenated key exits 3, which is not a valid pub package name so I did not count it.
  • bin/sync-instructions --check - exit 0, mirrors current.
  • Confirmed bin/check cds to the repo root before the relative python3 bin/parse-overrides.py call, and that *.pyc is already gitignored so the test job leaves the tree clean (git status clean after the run).
  • Not run: flutter test / the PHP suite - no backend/vendor here.
  • Not re-reviewed: everything outside these three files, unchanged since 4df2516.

…d branches on

Fifth review round, down to two narrow ones. A package entry whose value is a
YAML anchor or tag (`magic: &m` with the block child on the next lines) was
never pushed onto the stack, so the child's `path:` was swallowed and a stale
path passed silently without reaching the exit-3 branch. An anchor is not the
entry's value, it decorates what follows, so the entry is pushed now. Both rows
go red on the previous behaviour with the exact reported symptom.

The table also stopped at scan(), which left the loud half hand-verified, and
the loud half is the point: bin/check branches on the exit code, and 2 and 3 are
what turn a bad file into a failure rather than a silent pass. Four exit-code
checks run main() through a temporary file for each.

AGENTS.md's list of what bin/check runs did not name the overrides-parser job,
and the .github mirror carried the same omission because AGENTS.md itself had
not changed. Both name it now.
@anilcancakir

Copy link
Copy Markdown
Contributor Author

Both fixed, and the second one is the more interesting note.

The anchor. Reproduced exactly as you had it, then covered by two rows (&m and !!map), which go red on the previous behaviour with the reported symptom:

FAIL anchor before a block child: expected ['magic -> /nonexistent/anchor'], got []
FAIL tag before a block child: expected ['magic -> /nonexistent/tag'], got []

An anchor or tag is not the entry's value, it decorates the block child that follows, so the entry is pushed onto the stack rather than treated as a scalar.

The exit codes, which you flagged as still hand-verified. That was the sharper point, because the exit code is the whole behaviour: bin/check branches on $status, and 2 and 3 are what turn a bad file into a loud failure instead of the silent pass this all started as. A table that stopped at scan() left exactly the loud half untested. Four checks now run main() through a temporary file each: 0 on healthy, 0 on stale (findings go to stdout, not the exit code), 2 on an unopenable file, 3 on an unreadable shape.

Adding them surfaced a small thing in the instrument itself: the summary line still divided by the shape count, so the moment a second family of checks existed it would have reported 31/27. It counts both halves now.

parse-overrides: 31/31 checks pass (27 shapes, 4 exit codes)

AGENTS.md. Correct, and I counted rather than incremented: bin/check runs ten jobs. The uptizm side said "nine jobs" and this side's enumeration omitted the new one; both name it now, and the .github/ mirror is regenerated.

Also confirming your two environment checks from my side, since they are easy to get wrong: bin/check does cd "$REPO_ROOT" before the relative python3 bin/parse-overrides.py call, and git status is clean after a run.

bin/check green on both halves. Same commit on uptizm#142.

@anilcancakir
anilcancakir merged commit ef10e02 into main Sep 5, 2026
6 checks passed
@anilcancakir
anilcancakir deleted the feature/agent-tooling-mirror branch September 5, 2026 23:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant